package com.zjhcsoft.auth.service.impl;

import com.zjhcsoft.auth.common.enums.PasswordType;
import com.zjhcsoft.auth.common.enums.StatusCode;
import com.zjhcsoft.auth.common.utils.RandomUtils;
import com.zjhcsoft.auth.common.vo.Result;
import com.zjhcsoft.auth.entity.*;
import com.zjhcsoft.auth.entity.web.*;
import com.zjhcsoft.auth.service.*;
import com.zjhcsoft.auth.dao.AccountMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 账号表 服务实现类
 * </p>
 *
 * @author wzya
 * @since 2021-03-26
 */
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements
    AccountService {

    @Autowired
    UserCredentialService credentialService;
    @Autowired
    AppResourceService appService;
    @Autowired
    UserService userService;
    @Autowired
    private PasswordService passwordService;
    @Autowired
    CorporationService corporationService;
    @Autowired
    UserDeviceService userDeviceService;
    @Override
    public Account getAccountByChannelAndCorporationAndCredential(String channelCode, String corporationCode, String credential) {
        AppResource app = appService.getAppResourceByChannelCodeAndCorporationCode(channelCode,corporationCode);
        //通过凭证获取账号列表
        List<Long> accountIds = credentialService.lambdaQuery().
                eq(UserCredential::getCredential,credential).
                eq(UserCredential::getCredentialStatus, StatusCode.ON.getCode()).list().stream().map(userCredential ->userCredential.getAccountId()).collect(Collectors.toList());
        //凭证-业务系统确定唯一账号
        Account account = this.lambdaQuery().
                in(Account::getId,accountIds).
                eq(Account::getAppId,app.getId()).one();
        return account;
    }

    @Override
    public Account getAccountByChannelAndCorporationAndClientNo(String channelCode, String corporationCode, String clientNo) {
        User user = userService.lambdaQuery().eq(User::getClientNo,clientNo).one();
        AppResource app = appService.getAppResourceByChannelCodeAndCorporationCode(channelCode,corporationCode);
        Account account = this.lambdaQuery().eq(Account::getSysUserId,user.getId()).eq(Account::getAppId,app.getId()).one();
        return account;
    }

    @Override
    public Result queryCheckType(QueryCheckTypesRequest request) {
        Account account = this.getAccountByChannelAndCorporationAndCredential(request.getChannelCode(),request.getCorporationCode(),request.getUserCredential());
        List<Password> list = passwordService.lambdaQuery().eq(Password::getAccountId,account.getId()).select(Password::getCheckType,Password::getPasswordStatus).list();
        return Result.ok(list);
    }

    @Override
    public Result updateCheckType(UpdateCheckTypeRequest request) {
        Account account = this.getAccountByChannelAndCorporationAndCredential(request.getChannelCode(),request.getCorporationCode(),request.getUserCredential());
        //static不可变更，默认开启
        if(PasswordType.STATIC.getCode().equals(request.getCheckType())) {
            return Result.error("static password Cannot be closed.");
        }

        Password password = passwordService.lambdaQuery().eq(Password::getAccountId,account.getId()).eq(Password::getCheckType,request.getCheckType()).one();
        //操作类型，0-开 1-关
        if("0".equals(request.getOperatorType())){
            //已存在
            if(null!=password){
                //重复开通
                if(StatusCode.ON.getCode().equals(password.getPasswordStatus())){
                    return Result.error(" this check type already has been opened.");
                }else {
                    if(PasswordType.GESTURE.getCode().equals(request.getCheckType())){
                        password.setPassward(request.getPassword());
                    }
                    password.setPasswordStatus(StatusCode.ON.getCode());
                    passwordService.updateById(password);
                    return updateCheckTypeResponse(password);
                }
            }else {
                Password newPassword = new Password();
                newPassword.setAccountId(account.getId());
                newPassword.setCheckType(request.getCheckType());
                newPassword.setPasswordStatus(StatusCode.ON.getCode());
                if(PasswordType.GESTURE.getCode().equals(request.getCheckType())){
                    newPassword.setPassward(request.getPassword());
                }else {
                    newPassword.setPassward(RandomUtils.randomStr(32));
                }
                passwordService.save(newPassword);
                return updateCheckTypeResponse(newPassword);
            }
        }else if("1".equals(request.getOperatorType())){
            if(null!=password){
                //重复关闭
                if(StatusCode.OFF.getCode().equals(password.getPasswordStatus())){
                    return Result.error(" this check type already has been closed.");
                }else {
                    password.setPasswordStatus(StatusCode.OFF.getCode());
                    return updateCheckTypeResponse(password);
                }
            }else {
                return Result.error(" this check type not open.");
            }
        }else {
            return Result.error(" wrong operation type.");
        }
    }

    /**组装校验方式返回***/
    private Result updateCheckTypeResponse(Password password){
        if(PasswordType.CLIENT_FACE.getName().equals(password.getCheckType()) ||
                PasswordType.CLIENT_FINGER.getName().equals(password.getCheckType())){
            return Result.ok(password.getPassward());
        }else {
            return Result.ok("operation success.");
        }
    }

    @Override
    public Result queryCorporation(QueryCorporationRequest request) {
        Account account = this.getAccountByChannelAndCorporationAndCredential(request.getChannelCode(),request.getCorporationCode(),request.getUserCredential());
        List<Long> appIds = this.lambdaQuery().eq(Account::getSysUserId,account.getSysUserId()).select(Account::getAppId).list().stream().map(account1 -> account1.getAppId()).distinct().collect(Collectors.toList());
        List<Long> corporationIds = appService.lambdaQuery().in(AppResource::getId,appIds).list().stream().map(appResource -> appResource.getCorporationId()).distinct().collect(Collectors.toList());
        List<Corporation> corporations = corporationService.lambdaQuery().in(Corporation::getId,corporationIds).list();
        return Result.ok(corporations);
    }

    @Override
    public Result queryUserInfo(QueryUserInfoRequest request) {
        Account account = this.getAccountByChannelAndCorporationAndCredential(request.getChannelCode(),request.getCorporationCode(),request.getUserCredential());
        User user = userService.getById(account.getSysUserId());
        if(null!=user){
            user.setRegisterTime(user.getCreatedTime());
            return Result.ok(user);
        }else {
            return Result.error("invalid credential.");
        }
    }

    @Override
    public Result queryDevice(QueryDeviceRequest request) {
        Account account = this.getAccountByChannelAndCorporationAndCredential(request.getChannelCode(),request.getCorporationCode(),request.getUserCredential());
        List<UserDevice> devices = userDeviceService.lambdaQuery().eq(UserDevice::getAccountId,account.getId()).list();
        devices.stream().forEach(device-> device.setLoginNo(request.getUserCredential()) );
        return Result.ok(devices);
    }

}
